/**
   @file sys_usw_acl.h

   @date 2015-11-01

   @version v3.0

 */
#ifndef _SYS_USW_ACL_H
#define _SYS_USW_ACL_H

#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************
*
* Header Files
*
***************************************************************/
#include "ctc_const.h"
#include "ctc_macro.h"
#include "ctc_acl.h"
#include "ctc_field.h"
#include "ctc_spool.h"
#include "ctc_xdata.h"
#include "sys_usw_fpa.h"
#include "sys_usw_common.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_acl_api.h"
#include "sys_usw_xdata_api.h"
#include "sys_usw_acl_extract.h"
#include "sys_usw_ofb.h"
#include "sys_usw_parser.h"

/***************************************************************
*
*  Defines and Macros
*
***************************************************************/
#define SYS_ACL_UDF_PRI_2_IDX(prio)     (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) + MCHIP_CAP(SYS_CAP_ACL_UDF_KEY_ID_MIN) - prio - 1)
#define SYS_ACL_UDF_IDX_2_PRI(lchip, udf_entry)      p_usw_acl_master[lchip]->udf_fpa_en ? (udf_entry->fpae.priority):SYS_ACL_UDF_PRI_2_IDX(udf_entry->key_index)
#define SYS_ACL_UDF_HALF_FIELD_NUM      8 /*CTC_ACL_UDF_FIELD_NUM/2*/
#define SYS_ACL_INVALID_UDF_ID  0xFFFFFFFF

#define SYS_ACL_LEAGUE_UPDATE_PORT      0
#define SYS_ACL_LEAGUE_UPDATE_VLAN      1
#define SYS_ACL_LEAGUE_UPDATE_L3IF      2
#define SYS_ACL_LEAGUE_OP_NONE      0
#define SYS_ACL_LEAGUE_OP_SET       1
#define SYS_ACL_LEAGUE_OP_UPDATE    2
#define SYS_ACL_LEAGUE_OP_UNSET     3
#define SYS_ACL_LEAGUE_OP_CANCEL     4

#define SYS_USW_ACL_UDF_MAPPED_INDEX  0
#define SYS_USW_ACL_SUDF_AD_INDEX  1
#define SYS_USW_ACL_UDF_MAPPED_INDEX1  2


#define SYS_ACL_PRESEL_OP_MODE_ADD      1
#define SYS_ACL_PRESEL_OP_MODE_COPY     2
#define SYS_ACL_PRESEL_OP_MODE_DEL      3

#define SYS_ACL_FLOW_HASH_SINGLE        1
#define SYS_ACL_FLOW_HASH_DOUBLE        2
#define SYS_ACL_FLOW_HASH_QUAD          4


#define SYS_ACL_PRESEL_TCAM_DEPTH       32

#define ACL_IGS_BLOCK_MAX_NUM p_usw_acl_master[lchip]->igs_block_num
#define ACL_EGS_BLOCK_MAX_NUM p_usw_acl_master[lchip]->egs_block_num
#define ACL_XLOOKUP_BLOCK_MAX_NUM 1
#define SYS_ACL_IS_UDF_FIELD(field)     ((field)== CTC_FIELD_KEY_UDF || (field) == CTC_FIELD_KEY_UDF_AD_ID)

#define SYS_ACL_FK_SIZE(max_block_num,type)     \
        (sizeof(type) + sizeof(uint16)*max_block_num)
#define SYS_ACL_FLEX_KEY_IDX(dir, key_type) ((key_type)<<1)|(dir)
#define SYS_ACL_FLEX_KEY_VEC(lchip)         p_usw_acl_master[lchip]->flex_key_vec
#define SYS_ACL_DFT_FLEX_KEY_VEC(lchip)     p_usw_acl_master[lchip]->dft_flex_key_vec
#define SYS_ACL_PRESEL_VEC(lchip)           p_usw_acl_master[lchip]->presel_vec
#define SYS_ACL_IS_UDF_FIELD(field)     ((field)== CTC_FIELD_KEY_UDF || (field) == CTC_FIELD_KEY_UDF_AD_ID)
#define SYS_ACL_IS_SUDF_FIELD(field)     ((field)== CTC_FIELD_KEY_SUDF || (field) == CTC_FIELD_KEY_SUDF_AD_ID)
#define SYS_ACL_DECODE_FLEX_KEY_IDX(index, dir, key_type)   \
    {\
        (dir) = (index) & 1;\
        (key_type) = (index) >> 1;\
    }

#define SYS_ACL_GROUP_IS_PRESEL(pg) (CTC_FLAG_ISSET(pg->flag, SYS_ACL_GROUP_FLAG_PRESEL))   /* not only for tcam, hash also include */
#define SYS_ACL_FK_IS_FLEX_HASH0(fk) (fk && fk->node_type == SYS_ACL_FLEX_KEY_NODE_HASH && (0 != ((sys_acl_flex_hash_t*)fk)->origin_key_type))
#define SYS_ACL_GET_TBL_FUNC(lchip, pe, key_id, act_id, hw_index)  p_usw_acl_master[lchip]->get_table_id_func[SYS_ACL_GROUP_IS_PRESEL(pe->group)&&ACL_ENTRY_IS_TCAM(pe)](lchip, pe, key_id, act_id, hw_index)

#define SYS_ACL_DUMP_ERROR_RETURN(ret, str) \
    if (g_error_on) CTC_DEBUG_OUT_DUMP("Error Happened!! Fun:%s()  Line:%d ret:%d %s\n",__FUNCTION__,__LINE__, (ret), str); \
    return (ret)

#define SYS_ACL_GROUP_FLAG_PRESEL       (1U<<0)
#define SYS_ACL_UDE_RSV_PRI(RSV_TYPE) (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) - RSV_TYPE )
#define SYS_ACL_UDE_RSV_ID(RSV_TYPE) (0xFFFFFFFF - RSV_TYPE)
#define SYS_ACL_BLOCK_IS_UNMERGED(lchip, block_id) (SYS_ACL_BLOCK_STATUS_UNMERGE == p_usw_acl_master[lchip]->block[block_id].block_status)
#define SYS_ACL_IGS_BLK_LOOP(block_id, block_num)      for (block_id=0; block_id<block_num; block_id++)
#define SYS_ACL_PART_LOOP(part, part_num)   for (part=0; part<part_num; part++)
#define SYS_ACL_PART_LOOP_WITH_OP(part, part_num, op)  \
    SYS_ACL_PART_LOOP(part, part_num)   {\
        op;\
    }

#define SYS_ACL_PKSET_ADD(kset, field)  CTC_BMP_SET(((kset)->w), (field))
#define SYS_ACL_PKSET_REMOVE(kset, field)  CTC_BMP_UNSET(((kset)->w), (field))
#define SYS_ACL_PKSET_TEST(kset, field)  CTC_BMP_ISSET(((kset)->w), (field))


#define BLOCK_EMPTY(p_acb, part)    ((p_acb)[part].fpab.entry_count == (p_acb)[part].fpab.free_count)

#define ACL_SHARE_V(value, name)        value
#define ACL_SHARE_PTR(ptr, type)        ((type*)ptr)
#define SYS_ACL_ENCODE_IM_FLOW_INFO(flow_type,loss_prof_id,fih_type,delay_prof_id)  \
    ((delay_prof_id<<7)|(fih_type<<5)|(loss_prof_id<<2)|(flow_type))
#define SYS_ACL_DECODE_IM_FLOW_TYPE(data)  \
    (data&0x3)

#define SYS_ACL_IS_GLOBAL_PP_EN_LKUP(_lchip_, _dir_, _priority_) (((p_usw_acl_master[SYS_PP_BASE(_lchip_)]->global_pp_en_bmp[_dir_]) >> _priority_) & 0x01)
#define SYS_MAX_PP_NUM          8

#define SYS_ACL_KEY_SIZE_TO_PART_NUM(key_size, part_num)    {\
    switch(key_size)\
    {\
    case CTC_FPA_KEY_SIZE_160:\
        part_num = 1;\
        break;\
    case CTC_FPA_KEY_SIZE_320:\
        part_num = 2;\
        break;\
    case CTC_FPA_KEY_SIZE_640:\
        part_num = 3;\
        break;\
    default :\
        part_num = 1;\
        break;\
    }\
}

#define SYS_ACL_KEY_SIZE_TO_STEP(key_size, step)    {\
    switch(key_size)\
    {\
    case CTC_FPA_KEY_SIZE_160:\
        step = 0;\
        break;\
    case CTC_FPA_KEY_SIZE_320:\
        step = 1;\
        break;\
    case CTC_FPA_KEY_SIZE_640:\
        step = 1;\
        break;\
    default :\
        step = 0;\
        break;\
    }\
}


#define SYS_ACL_INIT_FK(block_num, type, p_fk)   \
{\
    type* p_flex_key = NULL; \
    MALLOC_ZERO(MEM_ACL_MODULE, p_fk, SYS_ACL_FK_SIZE(block_num,type)); \
    if (p_fk) \
    {   \
        p_flex_key = (type*)p_fk;\
        p_flex_key->entry_count = (void*)p_flex_key + sizeof(type);\
    }\
}

#define SYS_ACL_GET_STATS_ID(_stats_id, pe)\
if(0 == pe->ua_type && pe->ua)\
{\
    _stats_id = pe->ua->buffer.ad.tcam.stats_id;\
}\
else\
{\
    if(SYS_ACL_AD_TYPE_STATS == pe->ad_type)\
    {\
        _stats_id = pe->un.stats_id;\
    }\
    else if(pe->ua)\
    {\
        _stats_id = pe->ua->ad.stats_id;\
    }\
}

#define SYS_ACL_GET_NEXTHOP_ID(_nh_id, pe)\
if(0 == pe->ua_type && pe->ua)\
{\
    _nh_id = pe->ua->buffer.ad.tcam.nexthop_id;\
}\
else\
{\
    if(SYS_ACL_AD_TYPE_REDIRECT == pe->ad_type)\
    {\
        _nh_id = pe->un.nexthop_id;\
    }\
    else if(pe->ua)\
    {\
        _nh_id = pe->ua->ad.nexthop_id;\
    }\
}

#define SYS_ACL_GET_CPU_REASON_ID(_cpu_reason_id, pe)\
if(0 == pe->ua_type && pe->ua)\
{\
    _cpu_reason_id = pe->ua->buffer.ad.tcam.cpu_reason_id;\
}\
else\
{\
    if(SYS_ACL_AD_TYPE_EXCEPTION == pe->ad_type)\
    {\
        _cpu_reason_id = pe->un.g3.cpu_reason_id;\
    }\
    else if(pe->ua)\
    {\
        _cpu_reason_id = pe->ua->ad.cpu_reason_id;\
    }\
}

#define SYS_ACL_GET_LDP(_ldp, pe)\
if(0 == pe->ua_type && pe->ua)\
{\
    _ldp = pe->ua->buffer.ad.tcam.ldp;\
}\
else if(pe->ua)\
{\
    _ldp = pe->ua->ad.ldp;\
}

#define SYS_ACL_ASET_IS_DEF(aset_id)    ((!aset_id) || ((aset_id) > SYS_ACL_ASET_MAX))

enum sys_acl_xflow_field_e{
    SYS_XFLOW_UDF_VALID,
    SYS_XFLOW_UDF_HIT_INDEX,
    SYS_XFLOW_UDF_DATA0,
    SYS_XFLOW_UDF_DATA1,
    SYS_XFLOW_UDF_DATA2,
    SYS_XFLOW_UDF_DATA3,
    SYS_XFLOW_UDF_DATA4,
    SYS_XFLOW_UDF_DATA5,
    SYS_XFLOW_UDF_DATA6,
    SYS_XFLOW_UDF_DATA7,
    SYS_XFLOW_PORT_CID,
};

enum sys_acl_action_type
{
    SYS_ACL_ACTION_TCAM_INGRESS,
    SYS_ACL_ACTION_TCAM_EGRESS,
    SYS_ACL_ACTION_HASH_INGRESS,
    SYS_ACL_ACTION_NUM
};

typedef enum
{
    SYS_UDF_CAM_TYPE_FIB,
    SYS_UDF_CAM_TYPE_ACL,
    SYS_UDF_CAM_TYPE_SCL,
    SYS_UDF_CAM_TYPE_NUM
}sys_udf_cam_type_t;


#define SYS_ACL_ASET_MAX  253
#define SYS_ACL_DEF_ASET_EGS_TCAM   254
#define SYS_ACL_DEF_ASET_HASH   255

typedef struct sys_acl_aset_s {
    uint8   aset_id;
    
    uint8   xdata_prof_id  :3;
    uint8   rsv            :5;
    uint16  u1_type     : 3,
            u2_type     : 3,
            u3_type     : 3,
            u4_type     : 2,
            u5_type     : 1,
            type        : 3,
            is_static   : 1;

    uint32 ref_cnt;
    uint32 w[CTC_B2W_SIZE(CTC_ACL_FIELD_ACTION_NUM)];/*aset words*/
} sys_acl_aset_t;

struct sys_acl_fixed_key_s
{
    uint8  key_type;

    uint8  node_type;
    uint16 eth_type;
    
    uint32 entry_count;
    uint32 origin_key_type  :8;
    uint32 l3_type          :4;
    uint32 l4_type          :4;
    uint32 l4_user_type     :4;
    uint32 dir              :1;
    uint32 rsv              :11;
    sys_acl_kset_t kset;
};
typedef struct sys_acl_fixed_key_s sys_acl_fixed_key_t;

struct sys_acl_presel_temp_entry_s
{
    tbl_entry_t key;
    void*       ad;
    void*       profile;
};
typedef struct sys_acl_presel_temp_entry_s sys_acl_presel_temp_entry_t;

typedef struct
{
    uint32   stag_op   : 3,
             svid_sl   : 2,
             scos_sl   : 2,
             scfi_sl   : 2,
             
             ctag_op   : 3,
             cvid_sl   : 2,
             ccos_sl   : 2,
             ccfi_sl   : 2,
             tpid_en   : 1,
             tpid_index   : 2,
             is_global    :1,
             rsv1       : 10;

    uint16 profile_id; /* excluded in hash calculation */
    uint8 rsv[2];
}sys_acl_vlan_edit_t;

typedef struct
{
    uint32 stats_id;                          /*used for show action field: CTC_ACL_FIELD_ACTION_STATS*/
    //uint32 policer_id;                        /*used for show action field: per entry only have one of the three;
                                                //CTC_ACL_FIELD_ACTION_COPP; CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER; CTC_ACL_FIELD_ACTION_MACRO_FLOW_POLICER */
    uint32 nexthop_id;                        /*also used for show action field: CTC_ACL_FIELD_ACTION_REDIRECT & CTC_ACL_FIELD_ACTION_REDIRECT_PORT*/
    uint32 ad_index         : 20,
           rsv1             : 12;
           
    uint32 cpu_reason_id    : 10,
           ldp_valid        : 1,
           rsv              : 1,
           policer_mode     : 3,
           cos_index        : 3,
           lchip            : 8;
    uint32 calc_key_len[0];
    void*  ds;
    uint8 is_exist;
}sys_acl_hash_action_t;

typedef struct
{
    sys_acl_vlan_edit_t* vlan_edit; /*for tcam, add to vlan_edit_spool*/

    uint32 stats_id;                /*used for show action field: CTC_ACL_FIELD_ACTION_STATS*/
    uint32 nexthop_id;              /*also used for show action field: CTC_ACL_FIELD_ACTION_REDIRECT & CTC_ACL_FIELD_ACTION_REDIRECT_PORT*/
    uint32 cpu_reason_id    : 16,
           rsv              : 16;
    uint32 ldp;

    /*uint32 u1_type          : 2,
           u4_type          : 2,
           u2_type          : 3,
           u3_type          : 3,
           u5_type          : 3,
           rsv              : 2;*/
}sys_acl_tcam_action_t;
typedef struct
{
    ds_t key;
    ds_t mask;
    ds_t action;
    uint16 npm_metadata;
    sys_acl_flex_key_t* fk;
    sys_acl_aset_t* aset;
    sys_acl_kset_t kset;
    void* pa;
    union
    {
        sys_acl_hash_action_t hash;
        sys_acl_tcam_action_t tcam;
    } ad;
    ctc_xdata_t xdata;
}sys_acl_buffer_t;

struct sys_acl_lt_block_s
{
    uint8  block_id;
    /*uint8  valid;*/
    uint16  rsv;

    uint32 entry_valid;   /* offset_a as index, 0-15 key_valid, 16-31 action_valid */
    uint32 is_key160;
    uint32 ltid_bitmap;
    ctc_fpa_block_t fpab;

};
typedef struct sys_acl_lt_block_s   sys_acl_lt_block_t;

#define SYS_ACL_KEY_IS_RSVD(key_type)   (\
        (CTC_ACL_KEY_MAC        == key_type)    || (CTC_ACL_KEY_IPV4            == key_type)\
    ||  (CTC_ACL_KEY_IPV6       == key_type)    || (CTC_ACL_KEY_IPV4_EXT        == key_type)\
    ||  (CTC_ACL_KEY_MAC_IPV4   == key_type)    || (CTC_ACL_KEY_MAC_IPV4_EXT    == key_type)\
    ||  (CTC_ACL_KEY_IPV6_EXT   == key_type)    || (CTC_ACL_KEY_MAC_IPV6        == key_type)\
    ||  (CTC_ACL_KEY_CID        == key_type)    || (CTC_ACL_KEY_INTERFACE       == key_type)\
    ||  (CTC_ACL_KEY_FWD        == key_type)    || (CTC_ACL_KEY_FWD_EXT         == key_type)\
    ||  (CTC_ACL_KEY_COPP       == key_type)    || (CTC_ACL_KEY_COPP_EXT        == key_type)\
    ||  (CTC_ACL_KEY_UDF        == key_type)    || (CTC_ACL_KEY_STK_HDR         == key_type))
#define SYS_ACL_KEY_IS_FLEX(key_type)   ((CTC_ACL_KEY_FLEX_BASE <= key_type))
#define SYS_ACL_KEY_IS_FLEX_HASH0(action_type, key_type,priority)   ((action_type == SYS_ACL_ACTION_HASH_INGRESS) && \
(CTC_ACL_KEY_FLEX_BASE <= key_type) && (0 == priority))
#define SYS_ACL_FK(pe, type)            ((type*)pe->fk)
#define SYS_ACL_GET_FK(lchip, pe)  (0 == pe->ua_type && pe->ua) ? pe->ua->buffer.fk:\
MCHIP_ACL(lchip)->get_flex_key(lchip, pe->group->group_info.dir, pe->key_type)

struct sys_acl_presel_s
{
    ctc_fpa_entry_t fpae;       /* keep fpae head!! */
    uint32 presel_id    :16;
    uint32 dir          :2;
    uint32 lkup_level   :6;
    uint32 udf_en       :1;
    uint32 rsv          :7;

    uint32 flag;
    sys_acl_flex_key_t *fk;
    sys_acl_lt_block_t *pltb;
    sys_acl_buffer_t*   buffer;    /*lt key and ad*/
};
typedef struct sys_acl_presel_s   sys_acl_presel_t;


enum sys_acl_action_policer_mode
{
    SYS_ACL_ACTION_POLICER_MODE_NONE   = 0,
    SYS_ACL_ACTION_POLICER_MODE_MICRO_FLOW,
    SYS_ACL_ACTION_POLICER_MODE_MACRO_FLOW,
    SYS_ACL_ACTION_POLICER_MODE_COS_HBWP,
    SYS_ACL_ACTION_POLICER_MODE_COPP
};

typedef enum
{
    SYS_ACL_AD_TYPE_NONE = 0,       /* entry un is not used, or used for key */
    SYS_ACL_AD_TYPE_STATS,
    SYS_ACL_AD_TYPE_REDIRECT,
    SYS_ACL_AD_TYPE_EXCEPTION,
    SYS_ACL_AD_TYPE_LDP = SYS_ACL_AD_TYPE_EXCEPTION,
    
    SYS_ACL_AD_TYPE_DISABLE,        /* need ext tcam_ad */
    SYS_ACL_AD_TYPE_NUM
}sys_acl_ad_type_t;

#define SYS_ACL_ASET_LEVEL_ACTION   0
#define SYS_ACL_ASET_LEVEL_ENTRY    1
#define SYS_ACL_ASET_LEVEL_GROUP    2

typedef enum sys_acl_entry_flag_e
{
    SYS_ACL_ENTRY_FLAG_L3_TYPE  = (1U << 0),
    SYS_ACL_ENTRY_FLAG_L4_TYPE  = (1U << 1),
    SYS_ACL_ENTRY_FLAG_Y1731    = (1U << 2),
    SYS_ACL_ENTRY_FLAG_CLASS_ID = (1U << 3),
    SYS_ACL_ENTRY_FLAG_UDF      = (1U << 4),
    SYS_ACL_ENTRY_FLAG_SUDF     = (1U << 5),
    SYS_ACL_ENTRY_FLAG_NPM_IM_L_FLAG   = (1U << 6),
    SYS_ACL_ENTRY_FLAG_NPM_IM_D_FLAG   = (1U << 7),
    SYS_ACL_ENTRY_FLAG_SYS_BMP_MODEX   = (1U << 8),
    SYS_ACL_ENTRY_FLAG_LOGIC_PORT      = (1U << 9),     /*CTC_FIELD_KEY_LOGIC_SRC_PORT*/
    SYS_ACL_ENTRY_FLAG_SRH_COMMON_HDR  = (1U << 10),
    SYS_ACL_ENTRY_FLAG_GPORT           = (1U << 11),    /*CTC_FIELD_KEY_PORT*/
    SYS_ACL_ENTRY_FLAG_TUNNEL_INFO     = (1U << 12),
    SYS_ACL_ENTRY_FLAG_SMAC            = (1U << 13),
}sys_acl_entry_flag_t;

typedef enum sys_acl_xdata_chunk_e
{
    SYS_ACL_XDATA_IGS_CHUNK0_NIBBLE4    = (1U << 0),
    SYS_ACL_XDATA_IGS_CHUNK1_NIBBLE3_0  = (1U << 1),
    SYS_ACL_XDATA_IGS_CHUNK2_BYTE1_0    = (1U << 2),
    SYS_ACL_XDATA_IGS_CHUNK3_WORD0      = (1U << 3),
    SYS_ACL_XDATA_IGS_CHUNK3_WORD0_UDF  = (1U << 4),
    SYS_ACL_XDATA_IGS_CHUNK4_WORD1      = (1U << 5),
    SYS_ACL_XDATA_EGS_CHUNK0_NIBBLE4            = (1U << 6),
    SYS_ACL_XDATA_EGS_CHUNK1_NIBBLE3_0_BYTE0    = (1U << 7),
    SYS_ACL_XDATA_EGS_CHUNK2_BYTE1_WORD0        = (1U << 8),
    SYS_ACL_XDATA_EGS_CHUNK3_WORD1              = (1U << 9),
    /* Flow Hash */
    SYS_ACL_XDATA_FLOW_CHUNK0          = (1U << 10),
    SYS_ACL_XDATA_FLOW_CHUNK1          = (1U << 11),
    SYS_ACL_XDATA_FLOW_CHUNK2          = (1U << 12),
    SYS_ACL_XDATA_FLOW_CHUNK3          = (1U << 13),
    SYS_ACL_XDATA_FLOW_CHUNK4          = (1U << 14)/* udf exist */
}sys_acl_xdata_chunk_t;

/*only use for program acl*/
typedef enum
{
    SYS_ACL_KEY_SHARE_MODE_NONE,
    SYS_ACL_KEY_SHARE_MODE_PORT,            /*SYS_ACL_FIELD_GPORT_SHARE*/
    SYS_ACL_KEY_SHARE_MODE_LOGIC_PORT,      /*SYS_ACL_FIELD_LOGIC_PORT_SHARE*/
    SYS_ACL_KEY_SHARE_MODE_PBM,             /*SYS_ACL_FIELD_PBM*/
    SYS_ACL_KEY_SHARE_MODE_METADATA         /*CTC_FIELD_KEY_METADATA*/
} sys_acl_key_port_mode_t;

typedef enum
{
    SYS_ACL_FLOW_CID_NONE,
    SYS_ACL_FLOW_CID_DST,
    SYS_ACL_FLOW_CID_SRC,
    SYS_ACL_FLOW_CID_SERVICE,
    SYS_ACL_FLOW_CID_NSH
}sys_acl_flow_cid_mode_t;

typedef struct sys_acl_tcam_entry_s
{
    /*hash and tcam common start*/
    ctc_list_pointer_node_t head;   /* keep head top!! */
    sys_acl_group_t* group;         /* pointer to group node*/
    union
    {
        sys_acl_buffer_t buffer;
        sys_acl_tcam_action_t ad;
    }* ua;
    /*ctc_acl_aset_t* aset;*/
    uint32 key_type         : 8,    /* Refer to ctc_acl_key_type_t */
           aset_id          : 8,
           l3_type          : 4,
           l4_type          : 4,
           bind_nh          : 1,
           action_type      : 2,
           ua_type          : 1,    /*ua_type, 1-tcam ad, 0-buffer*/
           ip_dscp_mode     : 2,       /*0,none;1:dscp;2:ecn/PRECEDENCE*/
           key_mergedata_mode  : 2;       /*0,none;1:Wlan Info;2:MergeData*/

    /*hash and tcam common end*/
    ctc_fpa_entry_t fpae;                     /* keep fpae at second place!! */
    uint32 ad_type              : 3,               /* Refer to SYS_ACL_AD_TYPE_XXX */
           igmp_snooping        : 1,
           u1_type              : 2,
           u2_type              : 3,
           u3_type              : 3,
           u4_type              : 2,
           u5_type              : 2,
           flag                 : 15,    /*refer to sys_acl_entry_flag_t*/
           im_d_flag            : 1;

    uint32 l2_type                   : 2,
           l4_user_type              : 4,
           macl3basic_key_cvlan_mode : 2,       /*0,none;1:ip_da;  2:Aware Tunnel Info:CTC_FIELD_KEY_AWARE_TUNNEL_INFO*/
           macl3basic_key_macda_mode : 2,       /*0,none;1:mac_da; 2:Aware Tunnel Info:CTC_FIELD_KEY_AWARE_TUNNEL_INFO*/
           fwd_key_nsh_mode          : 2,       /*0,none;1:nsh;2:udf*/
           key_l4_port_mode          : 2,       /*0,none;1:l4port;2:vxlan;3:gre*/
           mac_key_vlan_mode         : 2,       /*0,none;1:svlan;2:cvlan*/
           im_l_flag                 : 1,
           npm_union_bmp             : 6,       /* bit0:ipfix, bit1:INT, bit2:IFA, bit3:npm_im_flow_0, bit4:npm_im_flow_1, bit5: metadata or fid */
           policer_mode              : 3,     /*Refer to sys_acl_action_policer_mode */
           key_port_mode             : 3,     /*[Fixed]0,none;1,port/logic_port/pbm; 2;metata_or_cid;[Program ACL] refer to sys_acl_key_port_mode_t*/
           cos_index                 : 3;    /*used for show action field: when policer is cos hbwp, point which policerptr to use*/

    union
    {
        uint32  stats_id;
        uint32  nexthop_id;
        struct{
            uint32  cpu_reason_id   : 16,
                    rsv             : 16;
        }g3;
        struct
        {
            uint16  range_bitmap;
            uint8   ether_type_index;
            uint8   wlan_bmp        : 3;       /*pe->wlan_bmp : 0,CTC_FIELD_KEY_WLAN_RADIO_MAC; 1,CTC_FIELD_KEY_WLAN_RADIO_ID; 2,CTC_FIELD_KEY_WLAN_CTL_PKT */
            uint8   ether_type_valid :1; 
            uint8   rsv             : 4;
        }g4;
    } un;
} sys_acl_entry_t;

typedef struct sys_acl_ldp_entry_s
{
    uint32 entry_id;
    ctc_list_pointer_node_t ldp_node;         /*for vxlan ldp tunnel update DsAcl*/
    ctc_list_pointer_node_t nhid_list_node;
}sys_acl_ldp_entry_t;

typedef struct sys_acl_hash_entry_s
{
    /*hash and tcam common start*/
    ctc_list_pointer_node_t head;   /* keep head top!! */
    sys_acl_group_t* group;         /* pointer to group node*/
    union
    {
        sys_acl_buffer_t buffer;
        sys_acl_hash_action_t ad;
    }* ua;
    uint32 key_type         : 8,    /* Refer to ctc_acl_key_type_t */
           aset_id          : 8,
           l3_type          : 4,
           l4_type          : 4,
           bind_nh          : 1,
           action_type      : 2,
           ua_type          : 1,    /*ua_type, 1-hash ad, 0-buffer*/
           rsv0             : 4;

    /*hash and tcam common end*/
    uint32 entry_id;                          /* keep entry_id at second place!! */

    uint32 hash_field_sel_id  : 8,          /* Hash select ID,if set to 0 ,indicate all field are vaild */
           hash_sel_tcp_flags : 2,
           u1_type            : 3,
           hash_valid         : 1,          /*generated hash index*/
           key_exist          : 1,          /*key exist*/
           key_conflict       : 1,          /*hash key conflict*/
           mac_key_vlan_mode  : 2,
           igmp_snooping      : 1,          /*[AT]*/
           priority           : 1,
           installed          : 1,
           cid_mode           : 3,      /* refer sys_acl_flow_cid_mode_t  */
           rsv                : 8;
    
    uint32 key_index          : 24,
           rsv2               : 8;
}sys_acl_hash_entry_t;

#define SYS_ACL_BLOCK_STATUS_UNMERGE    0
#define SYS_ACL_BLOCK_STATUS_MERGE_SRC  1
#define SYS_ACL_BLOCK_STATUS_MERGE_DST  2
struct sys_acl_block_s
{

    uint32 entry_num;           /*per block entry num by profile*/
    ctc_fpa_block_t fpab;
    uint32 block_id     : 8;
    uint32 expand_blk_id: 8;            /* merge to priority, only used for expand link block*/
    uint32 block_status : 2;      /*refer to SYS_ACL_BLOCK_STATUS_XXX*/
    uint32 valid        : 1;             /*if valid set, alloced, else empty*/
    uint32 rsv          : 13;

    struct sys_acl_block_s *prev;
    struct sys_acl_block_s *next;
    ctc_slist_t*     group_list;
};
typedef struct sys_acl_block_s sys_acl_block_t;
struct sys_acl_udf_buffer_s
{
    uint32 key[32];
    uint32 mask[32];
};
typedef struct sys_acl_udf_buffer_s sys_acl_udf_buffer_t;

struct sys_acl_udf_block_s
{
    ctc_fpa_block_t fpab;
};
typedef struct sys_acl_udf_block_s sys_acl_udf_block_t;
struct sys_acl_udf_entry_s
{
    ctc_fpa_entry_t fpae;
    uint32  key_index     :10 , /* DT2,TM: 0~15; TMM: 0~511, is_sudf means ad_index (515~1023,512,513,514 used in ipv6sr internal)*/
            is_sudf:1,
            rsv0 :6,
            key_index_used:1,
            ip_op         :1,
            ip_frag       :1 ,
            mpls_num      :1 ,
            l4_type       :4,
            udf_offset_num:5,  /* really write hw offset num */
            ip_protocol   :1,
            granularity   :1; /* for TMM, get/dump udf entry */
    uint32 udf_id ;
    uint32 offset_type_valid  :1,  /* for TM, TMM, get/dump udf entry, if offset_type_valid set, indicate use offset_type, not offset_type_array */
            is_installed :1,
            udf_hit_index :10, /* used to acl key udf_hit_index*/
            scl_offset_num:5,
            scl_key_valid:1,
            rsv1  :14;
    sys_acl_udf_buffer_t* buffer;
};
typedef struct sys_acl_udf_entry_s   sys_acl_udf_entry_t;

/*pkt-len-range and l4-port-range share the resource*/
#define SYS_ACL_FIELD_RANGE_NUM         16

#define SYS_ACL_ENTRY_OP_FLAG_ADD       1
#define SYS_ACL_ENTRY_OP_FLAG_DELETE    2

#define SYS_ACL_ACTION_FLAG_PERMIT      (1 << 0)
#define SYS_ACL_ACTION_FLAG_DISCARD     (1 << 1)
#define SYS_ACL_ACTION_FLAG_REDIRECT    (1 << 2)
#define SYS_ACL_ACTION_FLAG_LOG         (1 << 3)
#define SYS_ACL_ACTION_FLAG_BIND_NH         (1 << 4)
#define SYS_ACL_ACTION_FLAG_UNBIND_NH       (1 << 5)
#define SYS_ACL_ACTION_FLAG_COLOR_BASED     (1 << 6)


#define SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR 0xFFFFFF01
#define SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR 0xFFFFFF02

enum sys_acl_hash_gport_type
{
    ACL_HASH_GPORT_TYPE_NONE       = 0,
    ACL_HASH_GPORT_TYPE_GPORT      = 0x1,
    ACL_HASH_GPORT_TYPE_LOGIC_PORT = 0x2,
    ACL_HASH_GPORT_TYPE_METADATA   = 0x3,
    ACL_HASH_GPORT_TYPE_NUM
};


#define SYS_ACL_USW_GROUP_HASH_SIZE            1024
#define SYS_ACL_USW_ENTRY_HASH_SIZE            ( (SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_ACL_FLOW)/SYS_HASH_SIZE_COMPRESS_RATE_8) + \
                                                 (SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_ACL)/SYS_HASH_SIZE_COMPRESS_RATE_2) )
#define SYS_ACL_USW_HASH_ACTION_BLOCK_SIZE     4096
#define SYS_ACL_ASET_SIZE                  4096
#define SYS_ACL_ASET_DEF_NUM               SYS_ACL_ACTION_NUM

#define ACL_HASH_AD_RSV_NUM      5
#define ACL_HASH_SEL_RSV_NUM     4
#define ACL_HASH_AD_INDEX_OFFSET sizeof(DsFlow_m)/sizeof(uint32)
#define ACL_HASH_SEL_OFFSET      ACL_HASH_AD_INDEX_OFFSET + 1
#define ACL_XFLOW_PRIORITY_HIGHEST   1

#define ACL_BITMAP_STATUS_64    0 /* if only ipv6 exist*/
#define ACL_BITMAP_STATUS_16    1 /* if non-ipv6 exist*/

/* used by show only */
#define SYS_ACL_SHOW_IN_HEX   0xFFFFF

#define SYS_ACL_MAP_DRV_AD_INDEX(index, step)  ((1 == (step)) ? (index) : ((index) / 2))
#define SYS_ACL_MAP_DRV_KEY_INDEX(index, step)  ((index) / (step))

#define SYS_ACL_METADATA_CHECK(group_type)                      \
    if( (CTC_ACL_GROUP_TYPE_PORT_BITMAP == (group_type))        \
      || (CTC_ACL_GROUP_TYPE_PORT == (group_type))              \
      || (CTC_ACL_GROUP_TYPE_SERVICE_ACL == (group_type)) )      \
    {                                                           \
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Flag collision \n"); \
        return CTC_E_INVALID_CONFIG; \
                        \
    }

#define SYS_ACL_VLAN_ID_CHECK(vlan_id)           \
    {                                            \
        if ((vlan_id) > CTC_MAX_VLAN_ID) {       \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Vlan] Invalid vlan id \n");\
           return CTC_E_BADID;\
 } \
    }

#define SYS_ACL_VLAN_ACTION_RESERVE_NUM    63
#define SYS_USW_ACL_MATCH_GRP_MAX_COUNT    255
#define SYS_USW_ACL_GPORT_IS_LOCAL(lchip,gport) \
     (CTC_IS_LINKAGG_PORT(gport) || !SYS_GCHIP_IS_REMOTE(lchip,SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))

#define SYS_USW_ACL_HASH_VALID_CHECK(val)             \
    {                                                  \
        if (1 == val )                                 \
        {                                              \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry already exist \n");\
            return CTC_E_EXIST;\
        }                                              \
    }


#define SYS_USW_ACL_SET_BMP(bmp, bit, is_set) \
    do{\
        if(is_set)\
            CTC_BMP_SET(bmp, bit);\
        else\
            CTC_BMP_UNSET(bmp, bit);\
    }while(0)



#define SYS_USW_ACL_SET_BIT(flag, bit, is_set) \
    do{\
        if(is_set)\
            CTC_BIT_SET(flag, bit);\
        else\
            CTC_BIT_UNSET(flag, bit);\
    }while(0)

#define SYS_USW_SCL_TCAM_BASE 2
#define SYS_USW_ACL_TCAM_BASE 4
#define SYS_USW_FLOW_EXT_TCAM_BASE 15

#define SYS_USW_PRIVATE_TCAM_SIZE (drv_usw_get_flow_tcam_entry_num(lchip, mem_id))
#define SYS_USW_EXT_TCAM_SIZE   (drv_usw_get_flow_tcam_entry_num(lchip, ext_mem_id))
/* used for wb */
struct sys_acl_field_range_wb_data_s
{
    uint16  range_id_bitmap;
    uint16  range_id_ref[SYS_ACL_FIELD_RANGE_NUM];
    uint8   range_id_valid_cnt;
};
typedef struct sys_acl_field_range_wb_data_s sys_acl_field_range_wb_data_t;

/*  field range
*   l4_src_port_range and l4_dst_port_range share range_id from 0 ~ (SYS_ACL_L4_PORT_RANGE_NUM-1)
*   pkt_len_range range_id from SYS_ACL_L4_PORT_RANGE_NUM ~ (SYS_ACL_FIELD_RANGE_NUM - 1)
*/
typedef struct sys_acl_field_range_node_s
{
    uint8 range_id;

    uint8  range_type;
    uint16 udf_index : 15;
    uint16 is_sudf   : 1;
    uint8  udf_sel;
    uint8  rsv[3];
    uint16 udf_mask;
    uint16 ref;

    uint32 min;
    uint32 max;
} sys_acl_field_range_node_t;

struct sys_acl_field_range_s
{
    uint8  free_num;
    uint8  entry_num;
    uint8  is_fg_rg;
    uint8  dir;
    sys_acl_field_range_node_t range[SYS_ACL_FIELD_RANGE_NUM];

};
typedef struct sys_acl_field_range_s sys_acl_field_range_t;

/*cid hash action, used for spool*/
struct sys_acl_cid_action_s
{
    DsCategoryIdPair_m ds_cid_action;
    uint8              is_left;
    uint8              rsv;

    uint16              ad_index;

};
typedef struct sys_acl_cid_action_s sys_acl_cid_action_t;

struct sys_acl_register_s
{
    uint8  xgpon_gem_port_en;
};
typedef struct sys_acl_register_s   sys_acl_register_t;

enum sys_acl_global_property_e
{
    SYS_ACL_XGPON_GEM_PORT_EN,
    SYS_ACL_HASH_HALF_AD_EN
};
typedef enum sys_acl_global_property_e sys_acl_global_property_t;

struct sys_hash_sel_filed_union_s
{
    uint8   l4_port_field;          /*l4_port_field:  0:none; 1:gre/nvgre: 2:vxlan; 3:l4 port; 4:icmp; 5:igmp */
    uint8   l4_port_field_bmp;   /*for 1:gre/nvgre; bit0:CTC_FIELD_KEY_GRE_KEY;     bit1:CTC_FIELD_KEY_NVGRE_KEY;   (can't exist at the same time)
                                   for 2:vxlan;     CTC_FIELD_KEY_VN_ID     (only one field, no need l4_port_field_bmp)
                                   for 3:l4 port;   bit2:CTC_FIELD_KEY_L4_DST_PORT; bit3:CTC_FIELD_KEY_L4_SRC_PORT; (can exist at the same time)
                                   for 4:icmp;      bit4:CTC_FIELD_KEY_ICMP_CODE;   bit5:CTC_FIELD_KEY_ICMP_TYPE;   (can exist at the same time)
                                   for 5:igmp;      CTC_FIELD_KEY_IGMP_TYPE (only one field, no need l4_port_field_bmp)*/
    uint8   key_port_type;       /*0:none; 1:key port;   2:metadata*/
    uint8   l2_l3_key_ul3_type;  /*0:none; 1:ip; 2:mpls; 3:Unknown_etherType*/

       /*asic u1Type == 0 ��ʾipHeaderError/ipOptions/fragInfo/ttl/tcpFlags
        u1Type == 1 ��ʾipHeaderError/ipOptions/fragInfo/vrfId/isRouteMac
        u1Type == 2 ��ʾipPktLenRangeId/l4PortRangeBitmap/tcpFlags
        u1Type == 3 ipHeaderError/ipOptions/fragInfo/ttl/layer3HeaderProtocol */
    uint8   l3_key_u1_type : 4;   /*sw :asic u1Type+1 , 0:none; 1:g1; 2:g2; 3:g3; 4:g4. sw not support cfg l3_key_u1_type;default to 1*/
    uint8   l3_key_u1_bmp : 4;
    uint8   ipv6_key_ip_mode;   /*0:none;1;full ip;2:compress ip,sw not support cfg ipv6_key_ip_mode.default to 1*/

};
typedef struct sys_hash_sel_filed_union_s   sys_hash_sel_field_union_t;

typedef int32 (* SYS_CB_ACL_BUILD_KEY_FUNC_T)(uint8 lchip, ctc_field_key_t* pKey, sys_acl_entry_t* pe,uint8 is_add);
typedef int32 (* SYS_CB_ACL_GET_AD_FUNC_T)(uint8 lchip, ctc_acl_field_action_t* p_action, sys_acl_entry_t* pe);
typedef int32 (* SYS_CB_ACL_GET_TBL_ID_FUNC_T)(uint8 lchip, sys_acl_entry_t* pe, uint32* key_id, uint32* act_id, uint32* hw_index);
typedef int32 (* SYS_CB_ACL_SET_KEY_FIELDS_T)(uint8 lchip, ctc_acl_flex_key_t* acl_flex_key);

struct sys_acl_league_s
{
    uint8               block_id;
    uint8               size;
    uint16              lkup_level_start[ACL_IGS_BLK_MAX_NUM]; /*each merged lookup level start offset*/
    uint16              lkup_level_count[ACL_IGS_BLK_MAX_NUM];
    uint32              lkup_level_bitmap;
    uint8               hdr_block_id;
    uint8               merged_to;                                /*which priority this lookup level merged to*/
};
typedef struct sys_acl_league_s   sys_acl_league_t;

 struct sys_acl_udf_ad_s
 {
    uint16  ref_cnt;   /* use same udf_ad_id enry cnt */
 };
 typedef struct sys_acl_udf_ad_s   sys_acl_udf_ad_t;

#define SYS_ACL_UDF_AD_ID_MODE(lchip) p_usw_acl_master[lchip]->udf_ad_id_mode
enum sys_acl_udf_ad_id_mode
{
    SYS_ACL_UDF_AD_ID_MODE_NONE,
    SYS_ACL_UDF_AD_ID_MODE_DFT,
    SYS_ACL_UDF_AD_ID_MODE_USER
};

struct sys_acl_master_s
{
    ctc_hash_t          * group;            /* Hash table save group by gid.*/
    ctc_fpa_t           * fpa;              /* Fast priority arrangement. no array. */
    ctc_hash_t          * entry;            /* Hash table save hash|tcam entry by eid */
    ctc_spool_t         * ad_spool;         /* Share pool save hash action  */
    ctc_spool_t         * vlan_edit_spool;  /* Share pool save vlan edit  */
    ctc_spool_t         * cid_spool;        /* Share pool save cid hash action  */
    ctc_spool_t         * cethertype_spool[2][CTC_BOTH_DIRECTION]; /* Share pool save compress ether type */

    sys_acl_block_t     * block;
    sys_acl_lt_block_t  * lt_block;
    ctc_fpa_t           * presel_fpa;
    ctc_vector_t        * presel_vec;
    ctc_vector_t        * flex_key_vec;
    ctc_vector_t        * dft_flex_key_vec;
    ctc_vector_t        * fixed_key_vec;
    ctc_vector_t        * aset_vec;

    uint32              max_entry_priority;

    uint32              hash_sel_profile_count[SYS_ACL_HASH_KEY_TYPE_NUM][SYS_ACL_HASH_SEL_PROFILE_MAX];
    sys_hash_sel_field_union_t              hash_sel_key_union_filed[SYS_ACL_HASH_KEY_TYPE_NUM][SYS_ACL_HASH_SEL_PROFILE_MAX];

    sys_acl_league_t    * league;

    sys_acl_field_range_t *field_range[3];

    uint8               igs_block_num;      /* number of ingress logic lkup */
    uint8               egs_block_num;      /* number of egress logic lkup */
    uint8               opf_type_vlan_edit;
    uint8               opf_type_ad;    /*mark: in GG, this is managed in ftm*/
    uint8               ofb_type_cid;   /*category id tcam*/
    uint8               opf_type_cid_ad;
    uint8               opf_type_aset;
    uint8               opf_type_udf;   /*range: D2,TM: 0~15: TMM: 0~1024*/

    uint8               xflow_ad_couple         :1;
    uint8               udf_xdata_used          :1;
    uint8               ifa_ver                 :2;/* default 0: IFA2.0 , 1: IFA1.0 , 2: IFA2.0*/
    uint8               rsv                     :4;

    uint32              key_count[ACL_ALLOC_COUNT_NUM];
    sal_mutex_t*        acl_mutex;   /**< mutex for acl */

    uint8               udf_mode;               /*[AT]1:udf tmm mode;0:udf arctic mode */
    uint8               udf_ad_id_mode;         /*[AT]2:user asign udf_ad_id;1:sdk asign udf_ad_id;0:none*/
    uint16              udf_entry_cnt;          /*[AT]only counte udf_entry on pp_base*/
    ctc_hash_t          * udf_entry;            /* Hash table save udf entry by udf_id */
    ctc_vector_t        * udf_ad;               /* vector save udf action used info by udf_ad_id */
    sys_acl_udf_block_t  udf_block;
    ctc_fpa_t*           udf_fpa;

  //  sys_acl_udf_entry_t   udf_entry[SYS_ACL_MAX_UDF_ENTRY_NUM];
    SYS_CB_ACL_BUILD_KEY_FUNC_T build_key_func[CTC_ACL_KEY_FLEX_BASE];
    SYS_CB_ACL_GET_AD_FUNC_T    get_ad_func[SYS_ACL_ACTION_NUM];
    SYS_CB_ACL_GET_TBL_ID_FUNC_T get_table_id_func[2];  /*0: default, 1: program*/
    SYS_CB_ACL_SET_KEY_FIELDS_T  set_flex_key_fields[2];    /*0:tcam flex, 1:hash flex*/

    uint8               wlan_crypt_error_to_cpu;
    uint8               dot1ae_crypt_error_to_cpu;
    uint8               upa_en;   /*refer to ctc_acl_upa_mode_t*/

    uint8               league_update_bmp   :3;  /*bit0:update port, bit1:update vlan, bit2:update l3if*/
    uint8               glb_presel_en       :1;  /*0: per lkup presel, 1: global presel*/
    uint8               udf_fpa_en          :1;
    uint8               egs_league_update_bmp :3;

    //sys_acl_flex_group_t *p_fixed_fg;
    //sys_acl_flex_group_t *p_fixed_fg_user;

    sys_acl_kfield_cfg_info_db_t *kgn_field_cfg_info_db;
    sys_acl_kext_cfg_db_t *kgn_ext_cfg_db_arr[SYS_ACL_KEYGEN_MODE_COUNT];
    sys_acl_kset_t*     kset_db[CTC_ACL_KEY_FLEX_BASE];

    ctc_acl_kset_t*     support_kset;
    ctc_acl_aset_t*     support_aset;    /* ingress tcam and egress tcam, total action set */
    uint16              srv6_rsv_udf_idx;
    uint32*             replace_block_dma_buf;
    ctc_hash_t*         ldp_hash;
    ctc_hash_t*         nhid_hash;
    ctc_hash_t*         ldp_entry;
    void*               entry_hash_db[2];  /* pointer to ctc_at_acl_master */
    uint32              global_pp_en_bmp[CTC_BOTH_DIRECTION];  /* 0:disable pp global lookup, 1: enable pp global lookup */
    uint8               no_aset;
    uint32              default_base;
};
typedef struct sys_acl_master_s   sys_acl_master_t;


#define SYS_ACL_BLOCK(lchip, block_id) p_usw_acl_master[lchip]->block[block_id]

#define SYS_ACL_LT_BLOCK(lchip, block_id) p_usw_acl_master[lchip]->lt_block[block_id]

#define SYS_ACL_DBG_OUT(level, FMT, ...) \
    CTC_DEBUG_OUT(acl, acl, ACL_SYS, level, FMT, ## __VA_ARGS__)

#define SYS_ACL_DBG_FUNC() \
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__)

#define SYS_ACL_INIT_CHECK()         \
    {                                \
        LCHIP_CHECK(lchip);          \
        if (!p_usw_acl_master[lchip]) {           \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n"); \
         return CTC_E_NOT_INIT; \
 } \
    }

#define SYS_ACL_CREATE_LOCK(lchip)                   \
    do                                            \
    {                                             \
        sal_mutex_create(&p_usw_acl_master[lchip]->acl_mutex); \
        if (NULL == p_usw_acl_master[lchip]->acl_mutex)  \
        { \
            CTC_ERROR_RETURN(CTC_E_NO_MEMORY); \
        } \
    } while (0)

#define SYS_USW_ACL_LOCK(lchip) \
    if (p_usw_acl_master[lchip]->acl_mutex) sal_mutex_lock(p_usw_acl_master[lchip]->acl_mutex)

#define SYS_USW_ACL_UNLOCK(lchip) \
    if (p_usw_acl_master[lchip]->acl_mutex) sal_mutex_unlock(p_usw_acl_master[lchip]->acl_mutex)

#define SYS_USW_ACL_RETURN_UNLOCK(ret) \
do \
{ \
    sal_mutex_unlock(p_usw_acl_master[lchip]->acl_mutex); \
    return (ret); \
} while (0)

#define SYS_USW_ACL_ERROR_RETURN_UNLOCK(op) CTC_ERROR_RETURN_WITH_UNLOCK(op, p_usw_acl_master[lchip]->acl_mutex)

#define SYS_USW_ACL_CHECK_GROUP_UNEXIST_UNLOCK(pg)     \
    {                                       \
        if (!pg)                            \
        {                                   \
            sal_mutex_unlock(p_usw_acl_master[lchip]->acl_mutex); \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Group not exist \n"); \
            return CTC_E_NOT_EXIST;\
 \
        }                                   \
    }

/* input rsv group id , return failed */
#define SYS_ACL_IS_RSV_GROUP(gid) \
    ((gid) > CTC_ACL_GROUP_ID_NORMAL && (gid) < CTC_ACL_GROUP_ID_MAX)

#define SYS_ACL_CHECK_RSV_GROUP_ID(gid)      \
    {                                        \
        if SYS_ACL_IS_RSV_GROUP(gid)         \
        {                                    \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Group id reserved \n");\
            return CTC_E_BADID;\
 \
        }                                    \
    }

#define SYS_ACL_CHECK_GROUP_ID(gid)        \
    {                                      \
        if (gid >= CTC_ACL_GROUP_ID_MAX) { \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Invalid group id \n");\
            return CTC_E_BADID;\
 }   \
    }

#define SYS_ACL_CHECK_GROUP_TYPE(type)        \
    {                                         \
        if (type >= CTC_ACL_GROUP_TYPE_MAX) { \
            return CTC_E_ACL_GROUP_TYPE; }    \
    }

#define SYS_ACL_CHECK_GROUP_PRIO(dir, priority)                                      \
    {                                                                                \
        if (((CTC_INGRESS == dir) && (priority >= p_usw_acl_master[lchip]->igs_block_num)) || \
            ((CTC_EGRESS == dir) && (priority >= p_usw_acl_master[lchip]->egs_block_num)))    \
        {                                                                            \
            return CTC_E_INVALID_PARAM;                                         \
        }                                                                            \
    }

#define SYS_ACL_CHECK_ENTRY_PRIO(priority)               \
    {                                                    \
        if (priority > p_usw_acl_master[lchip]->max_entry_priority) { \
            return CTC_E_INVALID_PARAM; }           \
    }

#define SYS_ACL_SERVICE_ID_CHECK(sid)    SYS_LOGIC_PORT_CHECK(sid)

#define SYS_ACL_CHECK_GROUP_UNEXIST(pg)     \
    {                                       \
        if (!pg)                            \
        {                                   \
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Group not exist \n");\
            return CTC_E_NOT_EXIST;\
 \
        }                                   \
    }


#define ACL_ENTRY_IS_TCAM(pe) \
    ((SYS_ACL_ACTION_TCAM_INGRESS == (pe)->action_type) || (SYS_ACL_ACTION_TCAM_EGRESS == (pe)->action_type))

#define ACL_ENTRY_IS_INSTALLED(pe) \
    ((ACL_ENTRY_IS_TCAM(pe) && FPA_ENTRY_FLAG_INSTALLED == (pe)->fpae.flag) || (!ACL_ENTRY_IS_TCAM(pe) &&  TRUE == ((sys_acl_hash_entry_t*)(pe))->installed))

#define ACL_KEY_IS_TCAM(type)                                            \
    ((CTC_ACL_KEY_HASH_MAC != type) && (CTC_ACL_KEY_HASH_IPV4 != type) &&  \
     (CTC_ACL_KEY_HASH_MPLS != type) && (CTC_ACL_KEY_HASH_IPV6 != type) && \
     (CTC_ACL_KEY_HASH_L2_L3 != type) && (CTC_ACL_KEY_HASH_NSH != type))

#define ACL_ENTRY_IS_XFLOW(pe)  (pe->group->group_info.block_id >= 1)

#define ACL_SET_HW_MAC(d, s)    SYS_USW_SET_HW_MAC(d, s)
#define ACL_SET_HW_IP6(d, s)    SYS_USW_REVERT_IP6(d, s)
#define ACL_SET_HW_SATPDU_BYTE(d, s)    SYS_USW_REVERT_SATPDU_BYTE(d, s)
#define ACL_SET_HW_SCI_BYTE(d, s) SYS_USW_REVERT_SCI_BYTE(d, s)
#define ACL_SET_HW_UDF(d, s)    SYS_USW_REVERT_UDF(d, s)
#define ACL_SET_HW_UDF_72(d, s)    SYS_USW_REVERT_UDF_72(d, s)


#define ACL_GET_TABLE_ENTYR_NUM(lchip, t, n)    CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, t, n))
#define ACL_MAP_FLOW_STATS_BLOCK_ID(pe, pb, out_block_id, key_size) \
{\
    uint8 part = pe->fpae.offset_a/pb->fpab.entry_count;\
    uint8 block_base = (CTC_INGRESS == pe->group->group_info.dir) ? 0 : ACL_IGS_BLOCK_MAX_NUM;\
    uint32 _hw_index = pe->fpae.offset_a%pb->fpab.entry_count;\
    do {\
        if (_hw_index < pb->entry_num)\
        {\
            if ((key_size)>1)\
            {\
                out_block_id = pb->block_id + 1 - block_base;\
            }\
            else\
            {\
                out_block_id = pb->block_id + part - block_base;\
            }\
            break;\
        }\
        _hw_index -= pb->entry_num;\
        pb = pb->next;\
    }while (NULL != pb);\
}

#define ACL_MAP_FLOW_STATS_BLOCK_ID0(pe, out_block_id) \
{\
    uint8 idx = 0;\
    uint8 dir = pe->group->group_info.dir;\
    uint8 max_idx = (CTC_INGRESS == dir ? (ACL_IGS_BLOCK_MAX_NUM-1) : (ACL_EGS_BLOCK_MAX_NUM-1));\
    sys_acl_league_t* p_sys_league = &(p_usw_acl_master[lchip]->league[out_block_id]);\
    out_block_id = pe->group->group_info.block_id;\
    for (idx = max_idx; idx > out_block_id; idx--)\
    {\
        if (CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx) && (pe->fpae.offset_a >= p_sys_league->lkup_level_start[idx]))\
        {\
            out_block_id = idx;\
            break;\
        }\
    }\
}

#define SYS_USW_ACL_MAP_MEM2DESC(mem_id)   ((mem_id)+DRV_FTM_TCAM_KEY4-DRV_FTM_TCAM_KEY0+1)
#define SYS_USW_ACL_DMA_OP_SIZE  256
#define SYS_USW_ACL_UPA_EN(lchip,dir) \
(((p_usw_acl_master[lchip]->upa_en==CTC_ACL_UPA_BOTH_EN) || (dir == CTC_INGRESS && p_usw_acl_master[lchip]->upa_en==CTC_ACL_UPA_IGS_EN) || (dir == CTC_EGRESS && p_usw_acl_master[lchip]->upa_en==CTC_ACL_UPA_EGS_EN))?1:0)

struct drv_acl_group_info_s
{
    uint8  dir;

    uint32 class_id_data;
    uint32 class_id_mask;

    uint16 gport;
    uint16 gport_mask;

    uint8  gport_type;
    uint8  gport_type_mask;

    uint8  bitmap_base;
    uint8  bitmap_base_mask;

    uint8  bitmap;
    uint8  bitmap_mask;

    uint32 bitmap_64[2];
    uint32 bitmap_64_mask[2];

    uint8 update_class_id;
};
typedef struct drv_acl_group_info_s   drv_acl_group_info_t;

struct drv_acl_port_info_s
{
    uint8  dir;

    uint32 class_id_data;
    uint32 class_id_mask;

    uint16 gport;
    uint16 gport_mask;

    uint8  gport_type;
    uint8  gport_type_mask;

    uint8  bitmap_base;
    uint8  bitmap_base_mask;

    uint8  bitmap;
    uint8  bitmap_mask;

    uint32 bitmap_64[2];
    uint32 bitmap_64_mask[2];
};
typedef struct drv_acl_group_info_s  drv_acl_port_info_t;

typedef struct
{
    uint32             count;
    uint8              detail;
    uint8              entry_type; /*0:tcam;1;hash;2 :both */
    uint16             key_type;
    uint8              show_type;
    uint8              show_inner;
    uint8              rsv[2];
    ctc_field_key_t*   p_grep;
    uint8              grep_cnt;
    uint8              lchip;
} _acl_cb_para_t;

struct sys_usw_acl_league_node_s
{
    uint8 step;
    uint8 status;  /*has been moved*/
    uint8 old_block_id;
    uint16 old_index;
    uint32 entry_id;
    uint32 prio;
    sys_acl_buffer_t*  p_buffer;
};
typedef struct sys_usw_acl_league_node_s sys_usw_acl_league_node_t;

typedef uint16 sys_acl_fpa_ecnt_t[CTC_FPA_KEY_SIZE_NUM];

#define ACL_OUTER_ENTRY(pe)    ((sys_acl_entry_t *) ((uint8 *) pe - (intptr)(&((sys_acl_entry_t*)0)->fpae)))

extern const char *key_type_str[];

/*api from acl_func.c*/
extern int32
_sys_usw_acl_get_table_id(uint8 lchip, sys_acl_entry_t* pe, uint32* key_id, uint32* act_id, uint32* hw_index);
extern int32
_sys_usw_acl_program_get_table_id(uint8 lchip, sys_acl_entry_t* pe, uint32* key_id, uint32* act_id, uint32* hw_index);
extern int32
_sys_usw_acl_build_vlan_edit(uint8 lchip, void* p_ds_edit, sys_acl_vlan_edit_t* p_vlan_edit);
extern int32
_sys_usw_acl_add_hash_key_common_field(uint8 lchip, sys_acl_hash_entry_t* pe);
extern int32
_sys_usw_acl_add_key_common_field_group_none(uint8 lchip, sys_acl_entry_t* pe );
extern void
_sys_usw_acl_map_action_data(uint8 lchip, sys_acl_entry_t* pe, uint8 unmap);
extern int32
_sys_usw_acl_rebuild_buffer_from_hw(uint8 lchip, uint32 key_id, uint32 act_id, uint32 hw_index, sys_acl_entry_t* pe);
extern int32
_sys_usw_acl_read_from_hw(uint8 lchip, uint32 key_id, uint32 act_id, uint32 hw_index, sys_acl_entry_t* pe);
extern int32
_sys_usw_acl_remove_hw(uint8 lchip, sys_acl_entry_t* pe);
extern int32
_sys_usw_acl_add_hw(uint8 lchip, sys_acl_entry_t* pe, uint32* old_action);
extern int32
_sys_usw_acl_set_hash_sel_bmp(uint8 lchip, sys_acl_hash_entry_t* pe );
extern int32
_sys_usw_acl_set_register(uint8 lchip, sys_acl_register_t* p_reg);
extern int32
_sys_usw_acl_install_vlan_edit(uint8 lchip, sys_acl_vlan_edit_t* p_vlan_edit, uint16* p_prof_idx);
extern int32
_sys_usw_acl_get_hash_index(uint8 lchip, sys_acl_hash_entry_t* pe, uint8 is_lkup,uint8 install);
extern int32
_sys_usw_acl_add_hash_mac_key_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_ipv4_key_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_l2l3_key_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_ipv6_key_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_mpls_key_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_mac_sel_field(uint8 lchip, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_ipv4_sel_field(uint8 lchip, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_ipv6_sel_field(uint8 lchip, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_mpls_sel_field(uint8 lchip, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_add_hash_l2l3_sel_field(uint8 lchip, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_add_dsflow_field(uint8 lchip, ctc_acl_field_action_t* action_field, sys_acl_hash_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_get_field_action_hash_igs(uint8 lchip, ctc_acl_field_action_t* p_action, sys_acl_hash_entry_t* pe);
extern int32
_sys_usw_acl_add_mackey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_l3key160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_l3key320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_macl3key320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_macl3key640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_ipv6key320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_ipv6key640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_macipv6key640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_cidkey160_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_shortkey80_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_forwardkey320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_forwardkey640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_coppkey320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_coppkey640_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_add_udfkey320_field(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_operate_key_field(uint8 lchip, sys_acl_entry_t* pe_lkup, ctc_field_key_t* key_field, uint8 is_add);
extern int32
_sys_usw_acl_add_dsacl_field(uint8 lchip, ctc_acl_field_action_t* action_field, sys_acl_entry_t* pe, uint8 is_half, uint8 is_add);
extern int32
_sys_usw_acl_add_dsacl_field2(uint8 lchip, ctc_acl_field_action_t* action_field, sys_acl_entry_t* pe, uint8 is_half, uint8 is_add);
extern int32
_sys_usw_acl_add_dsacl_field_wlan_error_to_cpu(uint8 lchip, ctc_acl_field_action_t* action_field, sys_acl_entry_t* pe, uint8 is_half, uint8 is_add);
extern int32
_sys_usw_acl_get_field_action_tcam_igs(uint8 lchip, ctc_acl_field_action_t* p_action, sys_acl_entry_t* pe);
extern int32
_sys_usw_acl_add_udf_entry_key_field(uint8 lchip,  uint32 udf_id, ctc_field_key_t* key_field,uint8 is_add);
extern int32
_sys_usw_acl_set_league_table(uint8 lchip, ctc_acl_league_t* league);
extern int32
_sys_usw_acl_tcam_cid_pair_lookup(uint8 lchip, ctc_acl_cid_pair_t* cid_pair, uint32* index_o);
extern int32
_sys_usw_acl_build_cid_pair_action(uint8 lchip, void* p_buffer, ctc_acl_cid_pair_t* cid_pair);
extern int32
_sys_usw_acl_add_hash_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair);
extern int32
_sys_usw_acl_add_tcam_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair);
extern int32
_sys_usw_acl_remove_tcam_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair);
extern int32
_sys_usw_acl_remove_hash_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair);
extern int32
_sys_usw_acl_set_cid_priority(uint8 lchip, uint8 is_src_cid, uint8* p_prio_arry);
extern int32
_sys_usw_acl_get_field_sel(uint8 lchip, uint8 key_type, uint8 field_sel_id, void* ds_sel);
extern int32
_sys_usw_acl_update_action(uint8 lchip, void* data, void* change_nh_param);
extern int32
_sys_usw_acl_update_dsflow_action(uint8 lchip, void* data, void* change_nh_param);
extern int32
_sys_usw_acl_vlan_tag_op_translate(uint8 lchip, uint8 op_in, uint8* o_op, uint8* o_mode);
extern int32
_sys_usw_acl_map_ethertype(uint16 ethertype, uint8* o_l3_type);

/*api from acl.c*/
extern uint8
_sys_usw_acl_get_key_size(uint8 lchip, uint8 by_key_type, sys_acl_entry_t * pe, uint8* o_step);
extern int32
_sys_usw_acl_bind_nexthop(uint8 lchip, sys_acl_entry_t* pe,uint32 nh_id,uint8 ad_type);
extern int32
_sys_usw_acl_unbind_nexthop(uint8 lchip, sys_acl_entry_t* pe);
extern int32
_sys_usw_acl_remove_field_range(uint8 lchip, uint8 dir, uint8 range_type, uint8 is_program, uint16* p_range_bitmap);
extern int32
_sys_usw_acl_add_field_range(uint8 lchip, uint8 dir, uint8 range_type, uint16 min, uint16 max, uint16* p_range_bitmap);
extern int32
__sys_usw_acl_add_field_range(uint8 lchip, sys_parser_range_op_ctl_t *p_range_ctl, uint16* p_range_bitmap);
extern int32
_sys_usw_acl_get_compress_ipv6_addr(uint8 lchip,sys_acl_entry_t* pe,uint8 is_da, ipv6_addr_t ipv6, ipv6_addr_t ipv6_64);
extern int32
_sys_usw_acl_get_ipv6_addr_from_compress(uint8 lchip,sys_acl_entry_t* pe,uint8 is_da, ipv6_addr_t in_ipv6_64, ipv6_addr_t out_ipv6_128);
extern int32
_sys_usw_acl_get_udf_info(uint8 lchip,  uint32 udf_id, sys_acl_udf_entry_t **p_udf_entry);
extern int32
_sys_usw_acl_get_udf_entry_by_ad_id(uint8 lchip, uint32 udf_ad_id, sys_acl_udf_entry_t**pp_udf_entry);
extern int32
_sys_usw_acl_check_vlan_edit(uint8 lchip, ctc_acl_vlan_edit_t*   p_ctc, uint8* vlan_edit);
extern int32
_sys_usw_acl_get_nodes_by_eid(uint8 lchip, uint32 eid, sys_acl_entry_t** pe, sys_acl_group_t** pg, sys_acl_block_t** pb);
extern int32
_sys_usw_acl_check_tcam_key_union(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_check_tcam_key_param(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_set_tcam_key_union(uint8 lchip, ctc_field_key_t* key_field, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_hash_traverse_cb_show_inner_gid(sys_acl_group_t* pg, _acl_cb_para_t* cb_para);
extern int32
_sys_usw_acl_hash_traverse_cb_show_outer_gid(sys_acl_group_t* pg, _acl_cb_para_t* cb_para);
extern int32
_sys_usw_acl_show_spool_status(uint8 lchip);
extern int32
_sys_usw_acl_show_entry_all(uint8 lchip, uint8 sort_type, uint16 key_type, uint8 detail, uint8 show_type, ctc_field_key_t* p_grep, uint8 grep_cnt, uint8 show_inner);
extern int32
_sys_usw_acl_show_entry_by_lkup_level(uint8 lchip, uint8 level, uint16 key_type, uint8 detail, uint8 show_type, ctc_field_key_t* p_grep, uint8 grep_cnt, uint8 show_inner);
extern int32
_sys_usw_acl_show_entry_by_priority(uint8 lchip, uint8 prio, uint16 key_type, uint8 detail, uint8 show_type, ctc_field_key_t* p_grep, uint8 grep_cnt, uint8 show_inner);
extern int32
_sys_usw_acl_show_entry_by_group_id(uint8 lchip, uint32 gid, uint16 key_type, uint8 detail, uint8 show_type, ctc_field_key_t* p_grep, uint8 grep_cnt, uint8 show_inner);
extern int32
_sys_usw_acl_show_entry_by_entry_id(uint8 lchip, uint32 eid, uint16 key_type, uint8 detail, uint8 show_type, ctc_field_key_t* p_grep, uint8 grep_cnt, uint8 show_inner);
extern int32
_sys_usw_acl_get_entry_by_eid(uint8 lchip, uint32 eid, sys_acl_entry_t** pe);
extern int32
_sys_usw_acl_get_group_by_gid(uint8 lchip, uint32 gid, sys_acl_group_t** o_group);
extern int32
_sys_usw_acl_create_group(uint8 lchip, uint32 group_id, ctc_acl_group_info_t* group_info);
extern int32
_sys_usw_acl_destroy_group(uint8 lchip, uint32 group_id);
extern int32
_sys_usw_acl_install_group(uint8 lchip, uint32 group_id, ctc_acl_group_info_t* group_info);
extern int32
_sys_usw_acl_uninstall_group(uint8 lchip, uint32 group_id);
extern int32
_sys_usw_acl_install_entry(uint8 lchip, sys_acl_entry_t* pe, uint8 flag, uint8 move_sw);
extern int32
_sys_usw_acl_add_entry(uint8 lchip, uint32 group_id, ctc_acl_entry_t* p_ctc_entry);
extern int32
_sys_usw_acl_remove_entry(uint8 lchip, uint32 entry_id);
extern int32
_sys_usw_acl_remove_all_entry(uint8 lchip, uint32 group_id);
extern int32
_sys_usw_acl_set_league_merge(uint8 lchip, sys_acl_league_t* p_league1, sys_acl_league_t* p_league2, uint8 auto_en);
extern int32
_sys_usw_acl_set_league_cancel(uint8 lchip, sys_acl_league_t* p_league1, sys_acl_league_t* p_league2);
extern int32
_sys_usw_acl_reorder_entry_scatter(uint8 lchip, sys_acl_league_t* p_sys_league);
extern int32
_sys_usw_acl_reorder_entry_down_to_up(uint8 lchip, sys_acl_league_t* p_sys_league);
extern int32
_sys_usw_acl_reorder_entry_up_to_down(uint8 lchip, sys_acl_league_t* p_sys_league);
extern int32
_sys_usw_acl_wb_mapping_group(sys_wb_acl_group_t* p_wb_acl_group, sys_acl_group_t* p_acl_group, uint8 is_sync);
extern int32
_sys_usw_acl_wb_mapping_entry(uint8 lchip, sys_wb_acl_tcam_entry_t* p_wb_acl_entry, sys_acl_entry_t* p_acl_entry, uint8 is_sync, void* p_range, ctc_list_pointer_t* list);
int32
_sys_usw_acl_wb_mapping_hash_entry(uint8 lchip, sys_wb_acl_hash_entry_t* p_wb_acl_entry, sys_acl_hash_entry_t* p_acl_entry, uint8 is_sync);
extern int32
_sys_usw_acl_wb_mapping_udf(sys_wb_acl_udf_entry_t* p_wb_udf, sys_acl_udf_entry_t* p_udf, uint8 is_sync);
extern int32
_sys_usw_acl_wb_sync_tcam_entry(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_wb_sync_hash_entry(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_wb_sync_aset(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_wb_sync_group(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_wb_sync_udf_entry(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_wb_mapping_flex_key(sys_wb_acl_flex_key_t* p_wb_acl_fk, void* p_acl_fk, uint8 is_sync, uint8 lchip);
extern void
_sys_usw_acl_wb_mapping_aset(uint8 lchip, sys_wb_acl_aset_t* p_wb_aset, sys_acl_aset_t* p_aset, uint8 is_sync);
extern int32
_sys_usw_acl_wb_sync_flex_key(void* bucket_data, void* user_data);
extern int32
_sys_usw_acl_free_entry_node_data(void* node_data, void* user_data);
extern int32
_sys_usw_acl_free_group_node_data(void* node_data, void* user_data);
extern int32
_sys_usw_acl_free_udf_entry_node_data(void* node_data, void* user_data);
extern int32
_sys_usw_acl_hash_traverse_cb_show_group(sys_acl_group_t* pg, _acl_cb_para_t* cb_para);
extern int32
_sys_usw_acl_unmap_group_info(uint8 lchip, ctc_acl_group_info_t* ctc, sys_acl_group_info_t* sys);
extern int32
_sys_usw_acl_add_group_key_port_field(uint8 lchip, uint32 entry_id,sys_acl_group_t* pg);
extern int32
sys_usw_acl_offset_map_chunk(ctc_xdata_field_t* field, uint8 dir, uint32* chunk_bmp_o, uint8 is_flowhash);
extern int32
_sys_usw_acl_aset_init(uint8 lchip);
extern int32
_sys_usw_acl_check_aset(uint8 lchip, uint8 dir,  sys_acl_aset_t* p_aset_prof);
extern int32
_sys_usw_acl_add_aset(uint8 lchip, uint8 ad_type, ctc_acl_aset_t* aset, sys_acl_aset_t** p_sys_aset);
extern int32
_sys_usw_acl_remove_aset(uint8 lchip, uint16 aset_idx);
extern int32
_sys_usw_acl_get_aset(uint8 lchip, uint16 aset_idx, sys_acl_aset_t** p_sys_aset);
extern int32
_sys_usw_acl_operate_aset(uint8 lchip, ctc_acl_aset_t* ctc_aset, uint8 action_type, sys_acl_aset_t** p_out);
extern void
_sys_usw_acl_update_aset_ref(uint8 lchip, uint8 aset_id);
extern int32
_sys_usw_acl_opf_init(uint8 lchip);
extern int32
_sys_usw_acl_ofb_init(uint8 lchip);
extern int32
_sys_usw_acl_init_def_aset(uint8 lchip);
extern int32
_sys_usw_acl_spool_init(uint8 lchip);
extern int32
_sys_usw_acl_init_league_bitmap(uint8 lchip);
extern int32
_sys_usw_acl_init_vlan_edit(uint8 lchip);
extern int32
_sys_usw_acl_init_global_cfg(uint8 lchip, ctc_acl_global_cfg_t* acl_global_cfg);
extern int32
_sys_usw_acl_create_rsv_group(uint8 lchip);
extern int32
_sys_usw_acl_update_key_count(uint8 lchip, sys_acl_entry_t* pe, uint8 is_add);
extern int32
_sys_usw_acl_check_hash_sel_field_union(uint8 lchip, uint8 hash_type, uint8 field_sel_id, ctc_field_key_t* sel_field);
extern int32
_sys_usw_acl_set_hash_sel_field_union(uint8 lchip, uint8 hash_type, uint8 field_sel_id, ctc_field_key_t* sel_field, uint8 is_add);
extern int32
_sys_usw_acl_check_udf_entry_key_field_union(uint8 lchip,  uint32 udf_id, ctc_field_key_t* key_field);
extern int32
_sys_usw_acl_set_udf_entry_key_field_union(uint8 lchip,  uint32 udf_id, ctc_field_key_t* key_field,uint8 is_add);
extern int32
sys_usw_acl_check_udf_ad_id_mode(uint8 lchip, ctc_acl_classify_udf_t* udf_entry);
extern int32
sys_usw_acl_count_udf_entry(uint8 lchip, ctc_acl_classify_udf_t* udf_entry, uint8 is_add)
;
extern int32
_sys_usw_acl_get_entry_count_on_lkup_level(uint8 lchip, uint8 block_id, uint8 level, uint32* count);
extern uint32
_sys_usw_acl_hash_make_entry(sys_acl_entry_t* pe);
extern bool
_sys_usw_acl_hash_compare_entry(sys_acl_entry_t* pe0, sys_acl_entry_t* pe1);
extern uint32
_sys_usw_acl_udf_hash_make_entry(sys_acl_udf_entry_t* pe_sys_udf);
extern bool
_sys_usw_acl_udf_hash_compare_entry(sys_acl_udf_entry_t* pe0_sys_udf, sys_acl_udf_entry_t* pe1_sys_udf);
extern uint32
_sys_usw_acl_hash_make_group(sys_acl_group_t* pg);
extern bool
_sys_usw_acl_hash_compare_group(sys_acl_group_t* pg0, sys_acl_group_t* pg1);
extern int32
_sys_usw_acl_install_build_key_fn(uint8 lchip);
extern int32
_sys_usw_acl_get_action_fn(uint8 lchip);
extern int32
_sys_usw_acl_get_block_by_pe_fpa(uint8 lchip, ctc_fpa_entry_t* pe, ctc_fpa_block_t** pb);
extern int32
_sys_usw_acl_entry_move_hw_fpa(uint8 lchip, ctc_fpa_entry_t* p_fpa_entry, int32 tcam_idx_new);
extern int32
_sys_usw_acl_l4type_ipprotocol_judge(uint8 lchip, uint8 key_type, uint8 hash_sel_id);
extern int32
sys_usw_acl_unmap_fwd_type(uint8 pkt_fwd_type_drv, uint8* o_pkt_fwd_type);
extern int32
_sys_usw_acl_unmap_ip_frag(uint8 lchip, uint32 frag_info_data, uint32 frag_info_mask, uint8* o_ctc_ip_frag, uint8* o_ctc_ip_frag_mask);
extern uint8
sys_tmm_acl_fk_parts_count(uint32 flags);
extern int32
sys_usw_acl_array_is_empty(uint8* array, uint32 len);

int32
sys_usw_acl_alloc_offset(uint8 lchip, sys_acl_block_t *pb, sys_acl_entry_t*pe, uint8 key_size);

int32
sys_usw_acl_entry_get_map_index(sys_acl_block_t * pb, int32 *tcam_idx, uint32* block_index);

extern int32
_sys_usw_acl_league_traverse_block(uint8 lchip, uint8 tmp_block_id, uint16* entry_base,
                                                ctc_linklist_t** node_list, uint16* sub_entry_num,
                                                uint16* sub_free_num, sys_usw_acl_league_node_t** node_array);

extern int32 _sys_usw_acl_league_move_entry(uint8 lchip, ctc_linklist_t** node_list, ctc_fpa_entry_t** p_tmp_entries,
                                                uint16* sub_entry_num, uint8 block_id, sys_usw_acl_league_node_t** node_array);
extern int32 _sys_usw_acl_adjust_ext_tcam(uint8 lchip, uint16 ext_tcam_bitmap);
extern int32 _sys_usw_acl_get_ext_tcam_status(uint8 lchip, uint8* level_status);
extern int32 _sys_usw_acl_get_key_size_bitmap(uint8 lchip, sys_acl_block_t* pb, uint8* p_key_used_bmp, uint8 dir);
extern int32 _sys_usw_acl_league_cancel_high_block(uint8 lchip, ctc_acl_league_t* league);
extern int32 _sys_usw_acl_league_merge_high_block(uint8 lchip, ctc_acl_league_t* league, uint8 merged_priority);
extern int32 _sys_usw_acl_udf_get_block_by_pe_fpa(uint8 lchip, ctc_fpa_entry_t* pe, ctc_fpa_block_t** pb);
extern int32 _sys_usw_acl_udf_move_hw_fpa(uint8 lchip, ctc_fpa_entry_t* p_fpa_entry, int32 tcam_idx_new);
extern int32 _sys_usw_acl_get_ordered_league_block(uint8 lchip, uint8 block_id, uint8 size, ctc_acl_league_t* league);
extern int32 _sys_usw_acl_change_stats_ptr_cb(uint8 lchip, uint32 new_stats_ptr, uint8 new_ram, void* user_data);
extern int32 _sys_usw_acl_replace_dma_copy(uint8 lchip, ctc_acl_replace_t* p_replace, uint8 merge_size);
extern int32 _sys_usw_acl_replace_dma_delete(uint8 lchip, ctc_acl_replace_t* p_replace, uint8 merge_size);
extern int32 _sys_usw_acl_replace_dma_with_sdb_copy(uint8 lchip, ctc_acl_replace_t* p_replace, uint8 merge_size);
extern int32 _sys_usw_acl_replace_dma_with_sdb_delete(uint8 lchip, ctc_acl_replace_t* p_replace, uint8 merge_size);

extern int32 _sys_usw_acl_replace_io_copy(uint8 lchip, ctc_acl_replace_t* p_replace);
extern int32 _sys_usw_acl_replace_io_delete(uint8 lchip, ctc_acl_replace_t* p_replace);
extern int32 sys_usw_acl_fpa_block_init(uint8 lchip, uint8 block_id);
extern void sys_usw_acl_split_fpa_block(uint8 lchip, uint16 entry_cnt, sys_acl_fpa_ecnt_t p_ecnt);
extern int32 sys_usw_acl_buffer_malloc(uint8 lchip, sys_acl_entry_t* pe, uint8 is_malloc);
extern uint16 sys_usw_acl_get_ether_type_by_index(uint8 lchip, sys_acl_entry_t* pe, uint8 cether_type_index);
extern void* sys_usw_acl_get_ldp_entry_by_eid(uint8 lchip, uint32 eid);
extern void   _sys_usw_acl_restore_xdata_sel(uint8 lchip, uint8 dir, sys_acl_flex_key_t* p_fk, uint32 hw_idx);
extern int32 _sys_usw_acl_check_xdata(uint8 lchip, uint8 action_type, sys_acl_group_t * pg, uint8 prof_id, uint32 * aset, ctc_xdata_t * in_xdata);
extern int32 sys_usw_acl_flow_hash_default_entry_init(uint8 lchip);
extern int32 _sys_usw_acl_build_flow_hash_default_entry(uint8 lchip, uint16 lport, uint8 is_add);


#ifdef __cplusplus
}
#endif
#endif


